home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-10-30 | 49.2 KB | 1,189 lines |
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- NNNNAAAAMMMMEEEE
- perlfaq8 - System Interaction ($Revision: 1.21 $, $Date: 1997/04/24
- 22:44:19 $)
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- This section of the Perl FAQ covers questions involving operating system
- interaction. This involves interprocess communication (IPC), control
- over the user-interface (keyboard, screen and pointing devices), and most
- anything else not related to data manipulation.
-
- Read the FAQs and documentation specific to the port of perl to your
- operating system (eg, the _p_e_r_l_v_m_s manpage, the _p_e_r_l_p_l_a_n_9 manpage, ...).
- These should contain more detailed information on the vagaries of your
- perl.
-
- HHHHoooowwww ddddoooo IIII ffffiiiinnnndddd oooouuuutttt wwwwhhhhiiiicccchhhh ooooppppeeeerrrraaaattttiiiinnnngggg ssssyyyysssstttteeeemmmm IIII''''mmmm rrrruuuunnnnnnnniiiinnnngggg uuuunnnnddddeeeerrrr????
-
- The $^O variable ($OSTYPE if you use English) contains the operating
- system that your perl binary was built for.
-
- HHHHoooowwww ccccoooommmmeeee _e_x_e_c() doesn't return?
-
- Because that's what it does: it replaces your currently running program
- with a different one. If you want to keep going (as is probably the case
- if you're asking this question) use _s_y_s_t_e_m() instead.
-
- HHHHoooowwww ddddoooo IIII ddddoooo ffffaaaannnnccccyyyy ssssttttuuuuffffffff wwwwiiiitttthhhh tttthhhheeee kkkkeeeeyyyybbbbooooaaaarrrrdddd////ssssccccrrrreeeeeeeennnn////mmmmoooouuuusssseeee????
-
- How you access/control keyboards, screens, and pointing devices ("mice")
- is system-dependent. Try the following modules:
-
- Keyboard
-
- Term::Cap Standard perl distribution
- Term::ReadKey CPAN
- Term::ReadLine::Gnu CPAN
- Term::ReadLine::Perl CPAN
- Term::Screen CPAN
-
-
- Screen
-
- Term::Cap Standard perl distribution
- Curses CPAN
- Term::ANSIColor CPAN
-
-
- Mouse
-
- Tk CPAN
-
-
-
-
-
- PPPPaaaaggggeeee 1111
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- HHHHoooowwww ddddoooo IIII aaaasssskkkk tttthhhheeee uuuusssseeeerrrr ffffoooorrrr aaaa ppppaaaasssssssswwwwoooorrrrdddd????
-
- (This question has nothing to do with the web. See a different FAQ for
- that.)
-
- There's an example of this in the crypt entry in the _p_e_r_l_f_u_n_c manpage).
- First, you put the terminal into "no echo" mode, then just read the
- password normally. You may do this with an old-style _i_o_c_t_l() function,
- POSIX terminal control (see the _P_O_S_I_X manpage, and Chapter 7 of the
- Camel), or a call to the ssssttttttttyyyy program, with varying degrees of
- portability.
-
- You can also do this for most systems using the Term::ReadKey module from
- CPAN, which is easier to use and in theory more portable.
-
- HHHHoooowwww ddddoooo IIII rrrreeeeaaaadddd aaaannnndddd wwwwrrrriiiitttteeee tttthhhheeee sssseeeerrrriiiiaaaallll ppppoooorrrrtttt????
-
- This depends on which operating system your program is running on. In
- the case of Unix, the serial ports will be accessible through files in
- /dev; on other systems, the devices names will doubtless differ. Several
- problem areas common to all device interaction are the following
-
- lockfiles
- Your system may use lockfiles to control multiple access. Make sure
- you follow the correct protocol. Unpredictable behaviour can result
- from multiple processes reading from one device.
-
- open mode
- If you expect to use both read and write operations on the device,
- you'll have to open it for update (see the section on _o_p_e_n in the
- _p_e_r_l_f_u_n_c manpage for details). You may wish to open it without
- running the risk of blocking by using _s_y_s_o_p_e_n() and
- O_RDWR|O_NDELAY|O_NOCTTY from the Fcntl module (part of the standard
- perl distribution). See the section on _s_y_s_o_p_e_n in the _p_e_r_l_f_u_n_c
- manpage for more on this approach.
-
- end of line
- Some devices will be expecting a "\r" at the end of each line rather
- than a "\n". In some ports of perl, "\r" and "\n" are different from
- their usual (Unix) ASCII values of "\012" and "\015". You may have
- to give the numeric values you want directly, using octal ("\015"),
- hex ("0x0D"), or as a control-character specification ("\cM").
-
- print DEV "atv1\012"; # wrong, for some devices
- print DEV "atv1\015"; # right, for some devices
-
- Even though with normal text files, a "\n" will do the trick, there
- is still no unified scheme for terminating a line that is portable
- between Unix, DOS/Win, and Macintosh, except to terminate _A_L_L line
- ends with "\015\012", and strip what you don't need from the output.
- This applies especially to socket I/O and autoflushing, discussed
- next.
-
-
-
- PPPPaaaaggggeeee 2222
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- flushing output
- If you expect characters to get to your device when you _p_r_i_n_t() them,
- you'll want to autoflush that filehandle, as in the older
-
- use FileHandle;
- DEV->autoflush(1);
-
- and the newer
-
- use IO::Handle;
- DEV->autoflush(1);
-
- You can use _s_e_l_e_c_t() and the $| variable to control autoflushing (see
- the section on $| in the _p_e_r_l_v_a_r manpage and the select entry in the
- _p_e_r_l_f_u_n_c manpage):
-
- $oldh = select(DEV);
- $| = 1;
- select($oldh);
-
- You'll also see code that does this without a temporary variable, as
- in
-
- select((select(DEV), $| = 1)[0]);
-
- As mentioned in the previous item, this still doesn't work when using
- socket I/O between Unix and Macintosh. You'll need to hardcode your
- line terminators, in that case.
-
- non-blocking input
- If you are doing a blocking _r_e_a_d() or _s_y_s_r_e_a_d(), you'll have to
- arrange for an alarm handler to provide a timeout (see the alarm
- entry in the _p_e_r_l_f_u_n_c manpage). If you have a non-blocking open,
- you'll likely have a non-blocking read, which means you may have to
- use a 4-arg _s_e_l_e_c_t() to determine whether I/O is ready on that device
- (see the section on _s_e_l_e_c_t in the _p_e_r_l_f_u_n_c manpage.
-
- HHHHoooowwww ddddoooo IIII ddddeeeeccccooooddddeeee eeeennnnccccrrrryyyypppptttteeeedddd ppppaaaasssssssswwwwoooorrrrdddd ffffiiiilllleeeessss????
-
- You spend lots and lots of money on dedicated hardware, but this is bound
- to get you talked about.
-
- Seriously, you can't if they are Unix password files - the Unix password
- system employs one-way encryption. Programs like Crack can forcibly (and
- intelligently) try to guess passwords, but don't (can't) guarantee quick
- success.
-
- If you're worried about users selecting bad passwords, you should
- proactively check when they try to change their password (by modifying
- _p_a_s_s_w_d(1), for example).
-
-
-
-
-
- PPPPaaaaggggeeee 3333
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- HHHHoooowwww ddddoooo IIII ssssttttaaaarrrrtttt aaaa pppprrrroooocccceeeessssssss iiiinnnn tttthhhheeee bbbbaaaacccckkkkggggrrrroooouuuunnnndddd????
-
- You could use
-
- system("cmd &")
-
- or you could use fork as documented in the section on _f_o_r_k in the
- _p_e_r_l_f_u_n_c manpage, with further examples in the _p_e_r_l_i_p_c manpage. Some
- things to be aware of, if you're on a Unix-like system:
-
- STDIN, STDOUT and STDERR are shared
- Both the main process and the backgrounded one (the "child" process)
- share the same STDIN, STDOUT and STDERR filehandles. If both try to
- access them at once, strange things can happen. You may want to
- close or reopen these for the child. You can get around this with
- opening a pipe (see the section on _o_p_e_n in the _p_e_r_l_f_u_n_c manpage) but
- on some systems this means that the child process cannot outlive the
- parent.
-
- Signals
- You'll have to catch the SIGCHLD signal, and possibly SIGPIPE too.
- SIGCHLD is sent when the backgrounded process finishes. SIGPIPE is
- sent when you write to a filehandle whose child process has closed
- (an untrapped SIGPIPE can cause your program to silently die). This
- is not an issue with system("cmd&").
-
- Zombies
- You have to be prepared to "reap" the child process when it finishes
-
- $SIG{CHLD} = sub { wait };
-
- See the section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage for other examples
- of code to do this. Zombies are not an issue with system("prog &").
-
- HHHHoooowwww ddddoooo IIII ttttrrrraaaapppp ccccoooonnnnttttrrrroooollll cccchhhhaaaarrrraaaacccctttteeeerrrrssss////ssssiiiiggggnnnnaaaallllssss????
-
- You don't actually "trap" a control character. Instead, that character
- generates a signal, which you then trap. Signals are documented in the
- section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage and chapter 6 of the Camel.
-
- Be warned that very few C libraries are re-entrant. Therefore, if you
- attempt to _p_r_i_n_t() in a handler that got invoked during another stdio
- operation your internal structures will likely be in an inconsistent
- state, and your program will dump core. You can sometimes avoid this by
- using _s_y_s_w_r_i_t_e() instead of _p_r_i_n_t().
-
- Unless you're exceedingly careful, the only safe things to do inside a
- signal handler are: set a variable and exit. And in the first case, you
- should only set a variable in such a way that _m_a_l_l_o_c() is not called (eg,
- by setting a variable that already has a value).
-
-
-
-
-
- PPPPaaaaggggeeee 4444
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- For example:
-
- $Interrupted = 0; # to ensure it has a value
- $SIG{INT} = sub {
- $Interrupted++;
- syswrite(STDERR, "ouch\n", 5);
- }
-
- However, because syscalls restart by default, you'll find that if you're
- in a "slow" call, such as <FH>, _r_e_a_d(), _c_o_n_n_e_c_t(), or _w_a_i_t(), that the
- only way to terminate them is by "longjumping" out; that is, by raising
- an exception. See the time-out handler for a blocking _f_l_o_c_k() in the
- section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage or chapter 6 of the Camel.
-
- HHHHoooowwww ddddoooo IIII mmmmooooddddiiiiffffyyyy tttthhhheeee sssshhhhaaaaddddoooowwww ppppaaaasssssssswwwwoooorrrrdddd ffffiiiilllleeee oooonnnn aaaa UUUUnnnniiiixxxx ssssyyyysssstttteeeemmmm????
-
- If perl was installed correctly, the getpw*() functions described in the
- _p_e_r_l_f_u_n_c manpage provide (read-only) access to the shadow password file.
- To change the file, make a new shadow password file (the format varies
- from system to system - see the _p_a_s_s_w_d(_5) manpage for specifics) and use
- _p_w_d__m_k_d_b(8) to install it (see the _p_w_d__m_k_d_b(_5) manpage for more details).
-
- HHHHoooowwww ddddoooo IIII sssseeeetttt tttthhhheeee ttttiiiimmmmeeee aaaannnndddd ddddaaaatttteeee????
-
- Assuming you're running under sufficient permissions, you should be able
- to set the system-wide date and time by running the _d_a_t_e(1) program.
- (There is no way to set the time and date on a per-process basis.) This
- mechanism will work for Unix, MS-DOS, Windows, and NT; the VMS equivalent
- is set time.
-
- However, if all you want to do is change your timezone, you can probably
- get away with setting an environment variable:
-
- $ENV{TZ} = "MST7MDT"; # unixish
- $ENV{'SYS$TIMEZONE_DIFFERENTIAL'}="-5" # vms
- system "trn comp.lang.perl";
-
-
- HHHHoooowwww ccccaaaannnn IIII _s_l_e_e_p() or _a_l_a_r_m() for under a second?
-
- If you want finer granularity than the 1 second that the _s_l_e_e_p() function
- provides, the easiest way is to use the _s_e_l_e_c_t() function as documented
- in the section on _s_e_l_e_c_t in the _p_e_r_l_f_u_n_c manpage. If your system has
- itimers and _s_y_s_c_a_l_l() support, you can check out the old example in
- http://www.perl.com/CPAN/doc/misc/ancient/tutorial/eg/itimers.pl .
-
- HHHHoooowwww ccccaaaannnn IIII mmmmeeeeaaaassssuuuurrrreeee ttttiiiimmmmeeee uuuunnnnddddeeeerrrr aaaa sssseeeeccccoooonnnndddd????
-
- In general, you may not be able to. The Time::HiRes module (available
- from CPAN) provides this functionality for some systems.
-
-
-
-
-
- PPPPaaaaggggeeee 5555
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- In general, you may not be able to. But if you system supports both the
- _s_y_s_c_a_l_l() function in Perl as well as a system call like _g_e_t_t_i_m_e_o_f_d_a_y(2),
- then you may be able to do something like this:
-
- require 'sys/syscall.ph';
-
- $TIMEVAL_T = "LL";
-
- $done = $start = pack($TIMEVAL_T, ());
-
- syscall( &SYS_gettimeofday, $start, 0)) != -1
- or die "gettimeofday: $!";
-
- ##########################
- # DO YOUR OPERATION HERE #
- ##########################
-
- syscall( &SYS_gettimeofday, $done, 0) != -1
- or die "gettimeofday: $!";
-
- @start = unpack($TIMEVAL_T, $start);
- @done = unpack($TIMEVAL_T, $done);
-
- # fix microseconds
- for ($done[1], $start[1]) { $_ /= 1_000_000 }
-
- $delta_time = sprintf "%.4f", ($done[0] + $done[1] )
- -
- ($start[0] + $start[1] );
-
-
- HHHHoooowwww ccccaaaannnn IIII ddddoooo aaaannnn _a_t_e_x_i_t() or _s_e_t_j_m_p()/_l_o_n_g_j_m_p()? (Exception handling)
-
- Release 5 of Perl added the END block, which can be used to simulate
- _a_t_e_x_i_t(). Each package's END block is called when the program or thread
- ends (see the _p_e_r_l_m_o_d manpage manpage for more details). It isn't called
- when untrapped signals kill the program, though, so if you use END blocks
- you should also use
-
- use sigtrap qw(die normal-signals);
-
- Perl's exception-handling mechanism is its _e_v_a_l() operator. You can use
- _e_v_a_l() as setjmp and _d_i_e() as longjmp. For details of this, see the
- section on signals, especially the time-out handler for a blocking
- _f_l_o_c_k() in the section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage and chapter 6 of
- the Camel.
-
- If exception handling is all you're interested in, try the exceptions.pl
- library (part of the standard perl distribution).
-
-
-
-
-
-
- PPPPaaaaggggeeee 6666
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- If you want the _a_t_e_x_i_t() syntax (and an _r_m_e_x_i_t() as well), try the AtExit
- module available from CPAN.
-
- WWWWhhhhyyyy ddddooooeeeessssnnnn''''tttt mmmmyyyy ssssoooocccckkkkeeeettttssss pppprrrrooooggggrrrraaaammmm wwwwoooorrrrkkkk uuuunnnnddddeeeerrrr SSSSyyyysssstttteeeemmmm VVVV ((((SSSSoooollllaaaarrrriiiissss))))???? WWWWhhhhaaaatttt ddddooooeeeessss
- tttthhhheeee eeeerrrrrrrroooorrrr mmmmeeeessssssssaaaaggggeeee """"PPPPrrrroooottttooooccccoooollll nnnnooootttt ssssuuuuppppppppoooorrrrtttteeeedddd"""" mmmmeeeeaaaannnn????
-
- Some Sys-V based systems, notably Solaris 2.X, redefined some of the
- standard socket constants. Since these were constant across all
- architectures, they were often hardwired into perl code. The proper way
- to deal with this is to "use Socket" to get the correct values.
-
- Note that even though SunOS and Solaris are binary compatible, these
- values are different. Go figure.
-
- HHHHoooowwww ccccaaaannnn IIII ccccaaaallllllll mmmmyyyy ssssyyyysssstttteeeemmmm''''ssss uuuunnnniiiiqqqquuuueeee CCCC ffffuuuunnnnccccttttiiiioooonnnnssss ffffrrrroooommmm PPPPeeeerrrrllll????
-
- In most cases, you write an external module to do it - see the answer to
- "Where can I learn about linking C with Perl? [h2xs, xsubpp]". However,
- if the function is a system call, and your system supports _s_y_s_c_a_l_l(), you
- can use the syscall function (documented in the _p_e_r_l_f_u_n_c manpage).
-
- Remember to check the modules that came with your distribution, and CPAN
- as well - someone may already have written a module to do it.
-
- WWWWhhhheeeerrrreeee ddddoooo IIII ggggeeeetttt tttthhhheeee iiiinnnncccclllluuuuddddeeee ffffiiiilllleeeessss ttttoooo ddddoooo _i_o_c_t_l() or _s_y_s_c_a_l_l()?
-
- Historically, these would be generated by the h2ph tool, part of the
- standard perl distribution. This program converts _c_p_p(1) directives in C
- header files to files containing subroutine definitions, like
- &SYS_getitimer, which you can use as arguments to your functions. It
- doesn't work perfectly, but it usually gets most of the job done. Simple
- files like _e_r_r_n_o._h, _s_y_s_c_a_l_l._h, and _s_o_c_k_e_t._h were fine, but the hard ones
- like _i_o_c_t_l._h nearly always need to hand-edited. Here's how to install
- the *.ph files:
-
- 1. become super-user
- 2. cd /usr/include
- 3. h2ph *.h */*.h
-
- If your system supports dynamic loading, for reasons of portability and
- sanity you probably ought to use h2xs (also part of the standard perl
- distribution). This tool converts C header files to Perl extensions.
- See the _p_e_r_l_x_s_t_u_t manpage for how to get started with h2xs.
-
- If your system doesn't support dynamic loading, you still probably ought
- to use h2xs. See the _p_e_r_l_x_s_t_u_t manpage and the _E_x_t_U_t_i_l_s::_M_a_k_e_M_a_k_e_r
- manpage for more information (in brief, just use mmmmaaaakkkkeeee ppppeeeerrrrllll instead of a
- plain mmmmaaaakkkkeeee to rebuild perl with a new static extension).
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 7777
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- WWWWhhhhyyyy ddddoooo sssseeeettttuuuuiiiidddd ppppeeeerrrrllll ssssccccrrrriiiippppttttssss ccccoooommmmppppllllaaaaiiiinnnn aaaabbbboooouuuutttt kkkkeeeerrrrnnnneeeellll pppprrrroooobbbblllleeeemmmmssss????
-
- Some operating systems have bugs in the kernel that make setuid scripts
- inherently insecure. Perl gives you a number of options (described in
- the _p_e_r_l_s_e_c manpage) to work around such systems.
-
- HHHHoooowwww ccccaaaannnn IIII ooooppppeeeennnn aaaa ppppiiiippppeeee bbbbooootttthhhh ttttoooo aaaannnndddd ffffrrrroooommmm aaaa ccccoooommmmmmmmaaaannnndddd????
-
- The IPC::Open2 module (part of the standard perl distribution) is an
- easy-to-use approach that internally uses _p_i_p_e(), _f_o_r_k(), and _e_x_e_c() to
- do the job. Make sure you read the deadlock warnings in its
- documentation, though (see the _I_P_C::_O_p_e_n_2 manpage).
-
- WWWWhhhhyyyy ccccaaaannnn''''tttt IIII ggggeeeetttt tttthhhheeee oooouuuuttttppppuuuutttt ooooffff aaaa ccccoooommmmmmmmaaaannnndddd wwwwiiiitttthhhh _s_y_s_t_e_m()?
-
- You're confusing the purpose of _s_y_s_t_e_m() and backticks (``). _s_y_s_t_e_m()
- runs a command and returns exit status information (as a 16 bit value:
- the low 8 bits are the signal the process died from, if any, and the high
- 8 bits are the actual exit value). Backticks (``) run a command and
- return what it sent to STDOUT.
-
- $exit_status = system("mail-users");
- $output_string = `ls`;
-
-
- HHHHoooowwww ccccaaaannnn IIII ccccaaaappppttttuuuurrrreeee SSSSTTTTDDDDEEEERRRRRRRR ffffrrrroooommmm aaaannnn eeeexxxxtttteeeerrrrnnnnaaaallll ccccoooommmmmmmmaaaannnndddd????
-
- There are three basic ways of running external commands:
-
- system $cmd; # using system()
- $output = `$cmd`; # using backticks (``)
- open (PIPE, "cmd |"); # using open()
-
- With _s_y_s_t_e_m(), both STDOUT and STDERR will go the same place as the
- script's versions of these, unless the command redirects them. Backticks
- and _o_p_e_n() read oooonnnnllllyyyy the STDOUT of your command.
-
- With any of these, you can change file descriptors before the call:
-
- open(STDOUT, ">logfile");
- system("ls");
-
- or you can use Bourne shell file-descriptor redirection:
-
- $output = `$cmd 2>some_file`;
- open (PIPE, "cmd 2>some_file |");
-
- You can also use file-descriptor redirection to make STDERR a duplicate
- of STDOUT:
-
-
-
-
-
-
- PPPPaaaaggggeeee 8888
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- $output = `$cmd 2>&1`;
- open (PIPE, "cmd 2>&1 |");
-
- Note that you _c_a_n_n_o_t simply open STDERR to be a dup of STDOUT in your
- Perl program and avoid calling the shell to do the redirection. This
- doesn't work:
-
- open(STDERR, ">&STDOUT");
- $alloutput = `cmd args`; # stderr still escapes
-
- This fails because the _o_p_e_n() makes STDERR go to where STDOUT was going
- at the time of the _o_p_e_n(). The backticks then make STDOUT go to a
- string, but don't change STDERR (which still goes to the old STDOUT).
-
- Note that you _m_u_s_t use Bourne shell (_s_h(1)) redirection syntax in
- backticks, not _c_s_h(1)! Details on why Perl's _s_y_s_t_e_m() and backtick and
- pipe opens all use the Bourne shell are in
- http://www.perl.com/CPAN/doc/FMTEYEWTK/versus/csh.whynot .
-
- You may also use the IPC::Open3 module (part of the standard perl
- distribution), but be warned that it has a different order of arguments
- from IPC::Open2 (see the _I_P_C::_O_p_e_n_3 manpage).
-
- WWWWhhhhyyyy ddddooooeeeessssnnnn''''tttt _o_p_e_n() return an error when a pipe open fails?
-
- It does, but probably not how you expect it to. On systems that follow
- the standard _f_o_r_k()/_e_x_e_c() paradigm (eg, Unix), it works like this:
- _o_p_e_n() causes a _f_o_r_k(). In the parent, _o_p_e_n() returns with the process
- ID of the child. The child _e_x_e_c()s the command to be piped to/from. The
- parent can't know whether the _e_x_e_c() was successful or not - all it can
- return is whether the _f_o_r_k() succeeded or not. To find out if the
- command succeeded, you have to catch SIGCHLD and _w_a_i_t() to get the exit
- status. You should also catch SIGPIPE if you're writing to the child --
- you may not have found out the _e_x_e_c() failed by the time you write. This
- is documented in the _p_e_r_l_i_p_c manpage.
-
- On systems that follow the _s_p_a_w_n() paradigm, _o_p_e_n() _m_i_g_h_t do what you
- expect - unless perl uses a shell to start your command. In this case the
- _f_o_r_k()/_e_x_e_c() description still applies.
-
- WWWWhhhhaaaatttt''''ssss wwwwrrrroooonnnngggg wwwwiiiitttthhhh uuuussssiiiinnnngggg bbbbaaaacccckkkkttttiiiicccckkkkssss iiiinnnn aaaa vvvvooooiiiidddd ccccoooonnnntttteeeexxxxtttt????
-
- Strictly speaking, nothing. Stylistically speaking, it's not a good way
- to write maintainable code because backticks have a (potentially
- humungous) return value, and you're ignoring it. It's may also not be
- very efficient, because you have to read in all the lines of output,
- allocate memory for them, and then throw it away. Too often people are
- lulled to writing:
-
- `cp file file.bak`;
-
- And now they think "Hey, I'll just always use backticks to run programs."
-
-
-
- PPPPaaaaggggeeee 9999
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- Bad idea: backticks are for capturing a program's output; the _s_y_s_t_e_m()
- function is for running programs.
-
- Consider this line:
-
- `cat /etc/termcap`;
-
- You haven't assigned the output anywhere, so it just wastes memory (for a
- little while). Plus you forgot to check $? to see whether the program
- even ran correctly. Even if you wrote
-
- print `cat /etc/termcap`;
-
- In most cases, this could and probably should be written as
-
- system("cat /etc/termcap") == 0
- or die "cat program failed!";
-
- Which will get the output quickly (as its generated, instead of only at
- the end ) and also check the return value.
-
- _s_y_s_t_e_m() also provides direct control over whether shell wildcard
- processing may take place, whereas backticks do not.
-
- HHHHoooowwww ccccaaaannnn IIII ccccaaaallllllll bbbbaaaacccckkkkttttiiiicccckkkkssss wwwwiiiitttthhhhoooouuuutttt sssshhhheeeellllllll pppprrrroooocccceeeessssssssiiiinnnngggg????
-
- This is a bit tricky. Instead of writing
-
- @ok = `grep @opts '$search_string' @filenames`;
-
- You have to do this:
-
- my @ok = ();
- if (open(GREP, "-|")) {
- while (<GREP>) {
- chomp;
- push(@ok, $_);
- }
- close GREP;
- } else {
- exec 'grep', @opts, $search_string, @filenames;
- }
-
- Just as with _s_y_s_t_e_m(), no shell escapes happen when you _e_x_e_c() a list.
-
- WWWWhhhhyyyy ccccaaaannnn''''tttt mmmmyyyy ssssccccrrrriiiipppptttt rrrreeeeaaaadddd ffffrrrroooommmm SSSSTTTTDDDDIIIINNNN aaaafffftttteeeerrrr IIII ggggaaaavvvveeee iiiitttt EEEEOOOOFFFF ((((^^^^DDDD oooonnnn UUUUnnnniiiixxxx,,,, ^^^^ZZZZ
- oooonnnn MMMMSSSS----DDDDOOOOSSSS))))????
-
- Because some stdio's set error and eof flags that need clearing. The
- POSIX module defines _c_l_e_a_r_e_r_r() that you can use. That is the
- technically correct way to do it. Here are some less reliable
- workarounds:
-
-
-
- PPPPaaaaggggeeee 11110000
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- 1 Try keeping around the seekpointer and go there, like this:
-
- $where = tell(LOG);
- seek(LOG, $where, 0);
-
-
- 2 If that doesn't work, try seeking to a different part of the file and
- then back.
-
- 3 If that doesn't work, try seeking to a different part of the file,
- reading something, and then seeking back.
-
- 4 If that doesn't work, give up on your stdio package and use sysread.
-
- HHHHoooowwww ccccaaaannnn IIII ccccoooonnnnvvvveeeerrrrtttt mmmmyyyy sssshhhheeeellllllll ssssccccrrrriiiipppptttt ttttoooo ppppeeeerrrrllll????
-
- Learn Perl and rewrite it. Seriously, there's no simple converter.
- Things that are awkward to do in the shell are easy to do in Perl, and
- this very awkwardness is what would make a shell->perl converter nigh-on
- impossible to write. By rewriting it, you'll think about what you're
- really trying to do, and hopefully will escape the shell's pipeline
- datastream paradigm, which while convenient for some matters, causes many
- inefficiencies.
-
- CCCCaaaannnn IIII uuuusssseeee ppppeeeerrrrllll ttttoooo rrrruuuunnnn aaaa tttteeeellllnnnneeeetttt oooorrrr ffffttttpppp sssseeeessssssssiiiioooonnnn????
-
- Try the Net::FTP, TCP::Client, and Net::Telnet modules (available from
- CPAN). http://www.perl.com/CPAN/scripts/netstuff/telnet.emul.shar will
- also help for emulating the telnet protocol, but Net::Telnet is quite
- probably easier to use..
-
- If all you want to do is pretend to be telnet but don't need the initial
- telnet handshaking, then the standard dual-process approach will suffice:
-
- use IO::Socket; # new in 5.004
- $handle = IO::Socket::INET->new('www.perl.com:80')
- || die "can't connect to port 80 on www.perl.com: $!";
- $handle->autoflush(1);
- if (fork()) { # XXX: undef means failure
- select($handle);
- print while <STDIN>; # everything from stdin to socket
- } else {
- print while <$handle>; # everything from socket to stdout
- }
- close $handle;
- exit;
-
-
- HHHHoooowwww ccccaaaannnn IIII wwwwrrrriiiitttteeee eeeexxxxppppeeeecccctttt iiiinnnn PPPPeeeerrrrllll????
-
-
-
-
-
-
- PPPPaaaaggggeeee 11111111
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- Once upon a time, there was a library called chat2.pl (part of the
- standard perl distribution), which never really got finished. These
- days, your best bet is to look at the Comm.pl library available from
- CPAN.
-
- IIIIssss tttthhhheeeerrrreeee aaaa wwwwaaaayyyy ttttoooo hhhhiiiiddddeeee ppppeeeerrrrllll''''ssss ccccoooommmmmmmmaaaannnndddd lllliiiinnnneeee ffffrrrroooommmm pppprrrrooooggggrrrraaaammmmssss ssssuuuucccchhhh aaaassss """"ppppssss""""????
-
- First of all note that if you're doing this for security reasons (to
- avoid people seeing passwords, for example) then you should rewrite your
- program so that critical information is never given as an argument.
- Hiding the arguments won't make your program completely secure.
-
- To actually alter the visible command line, you can assign to the
- variable $0 as documented in the _p_e_r_l_v_a_r manpage. This won't work on all
- operating systems, though. Daemon programs like sendmail place their
- state there, as in:
-
- $0 = "orcus [accepting connections]";
-
-
- IIII {{{{cccchhhhaaaannnnggggeeeedddd ddddiiiirrrreeeeccccttttoooorrrryyyy,,,, mmmmooooddddiiiiffffiiiieeeedddd mmmmyyyy eeeennnnvvvviiiirrrroooonnnnmmmmeeeennnntttt}}}} iiiinnnn aaaa ppppeeeerrrrllll ssssccccrrrriiiipppptttt.... HHHHoooowwww
- ccccoooommmmeeee tttthhhheeee cccchhhhaaaannnnggggeeee ddddiiiissssaaaappppppppeeeeaaaarrrreeeedddd wwwwhhhheeeennnn IIII eeeexxxxiiiitttteeeedddd tttthhhheeee ssssccccrrrriiiipppptttt???? HHHHoooowwww ddddoooo IIII ggggeeeetttt mmmmyyyy
- cccchhhhaaaannnnggggeeeessss ttttoooo bbbbeeee vvvviiiissssiiiibbbblllleeee????
-
- Unix
- In the strictest sense, it can't be done -- the script executes as a
- different process from the shell it was started from. Changes to a
- process are not reflected in its parent, only in its own children
- created after the change. There is shell magic that may allow you to
- fake it by _e_v_a_l()ing the script's output in your shell; check out the
- comp.unix.questions FAQ for details.
-
- VMS Change to %ENV persist after Perl exits, but directory changes do
- not.
-
- HHHHoooowwww ddddoooo IIII cccclllloooosssseeee aaaa pppprrrroooocccceeeessssssss''''ssss ffffiiiilllleeeehhhhaaaannnnddddlllleeee wwwwiiiitttthhhhoooouuuutttt wwwwaaaaiiiittttiiiinnnngggg ffffoooorrrr iiiitttt ttttoooo ccccoooommmmpppplllleeeetttteeee????
-
- Assuming your system supports such things, just send an appropriate
- signal to the process (see the section on _k_i_l_l in the _p_e_r_l_f_u_n_c manpage.
- It's common to first send a TERM signal, wait a little bit, and then send
- a KILL signal to finish it off.
-
- HHHHoooowwww ddddoooo IIII ffffoooorrrrkkkk aaaa ddddaaaaeeeemmmmoooonnnn pppprrrroooocccceeeessssssss????
-
- If by daemon process you mean one that's detached (disassociated from its
- tty), then the following process is reported to work on most Unixish
- systems. Non-Unix users should check their Your_OS::Process module for
- other solutions.
-
- +o Open /dev/tty and use the the TIOCNOTTY ioctl on it. See the _t_t_y(_4)
- manpage for details.
-
-
-
-
- PPPPaaaaggggeeee 11112222
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- +o Change directory to /
-
- +o Reopen STDIN, STDOUT, and STDERR so they're not connected to the old
- tty.
-
- +o Background yourself like this:
-
- fork && exit;
-
-
- HHHHoooowwww ddddoooo IIII mmmmaaaakkkkeeee mmmmyyyy pppprrrrooooggggrrrraaaammmm rrrruuuunnnn wwwwiiiitttthhhh sssshhhh aaaannnndddd ccccsssshhhh????
-
- See the _e_g/_n_i_h script (part of the perl source distribution).
-
- HHHHoooowwww ddddoooo IIII ffffiiiinnnndddd oooouuuutttt iiiiffff IIII''''mmmm rrrruuuunnnnnnnniiiinnnngggg iiiinnnntttteeeerrrraaaaccccttttiiiivvvveeeellllyyyy oooorrrr nnnnooootttt????
-
- Good question. Sometimes -t STDIN and -t STDOUT can give clues,
- sometimes not.
-
- if (-t STDIN && -t STDOUT) {
- print "Now what? ";
- }
-
- On POSIX systems, you can test whether your own process group matches the
- current process group of your controlling terminal as follows:
-
- use POSIX qw/getpgrp tcgetpgrp/;
- open(TTY, "/dev/tty") or die $!;
- $tpgrp = tcgetpgrp(TTY);
- $pgrp = getpgrp();
- if ($tpgrp == $pgrp) {
- print "foreground\n";
- } else {
- print "background\n";
- }
-
-
- HHHHoooowwww ddddoooo IIII ttttiiiimmmmeeeeoooouuuutttt aaaa sssslllloooowwww eeeevvvveeeennnntttt????
-
- Use the _a_l_a_r_m() function, probably in conjunction with a signal handler,
- as documented the section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage and chapter 6
- of the Camel. You may instead use the more flexible Sys::AlarmCall
- module available from CPAN.
-
- HHHHoooowwww ddddoooo IIII sssseeeetttt CCCCPPPPUUUU lllliiiimmmmiiiittttssss????
-
- Use the BSD::Resource module from CPAN.
-
- HHHHoooowwww ddddoooo IIII aaaavvvvooooiiiidddd zzzzoooommmmbbbbiiiieeeessss oooonnnn aaaa UUUUnnnniiiixxxx ssssyyyysssstttteeeemmmm????
-
-
-
-
-
-
- PPPPaaaaggggeeee 11113333
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- Use the reaper code from the section on _S_i_g_n_a_l_s in the _p_e_r_l_i_p_c manpage to
- call _w_a_i_t() when a SIGCHLD is received, or else use the double-fork
- technique described in the fork entry in the _p_e_r_l_f_u_n_c manpage.
-
- HHHHoooowwww ddddoooo IIII uuuusssseeee aaaannnn SSSSQQQQLLLL ddddaaaattttaaaabbbbaaaasssseeee????
-
- There are a number of excellent interfaces to SQL databases. See the
- DBD::* modules available from http://www.perl.com/CPAN/modules/dbperl/DBD
- .
-
- HHHHoooowwww ddddoooo IIII mmmmaaaakkkkeeee aaaa _s_y_s_t_e_m() exit on control-C?
-
- You can't. You need to imitate the _s_y_s_t_e_m() call (see the _p_e_r_l_i_p_c
- manpage for sample code) and then have a signal handler for the INT
- signal that passes the signal on to the subprocess.
-
- HHHHoooowwww ddddoooo IIII ooooppppeeeennnn aaaa ffffiiiilllleeee wwwwiiiitttthhhhoooouuuutttt bbbblllloooocccckkkkiiiinnnngggg????
-
- If you're lucky enough to be using a system that supports non-blocking
- reads (most Unixish systems do), you need only to use the O_NDELAY or
- O_NONBLOCK flag from the Fcntl module in conjunction with _s_y_s_o_p_e_n():
-
- use Fcntl;
- sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
- or die "can't open /tmp/somefile: $!":
-
-
- HHHHoooowwww ddddoooo IIII iiiinnnnssssttttaaaallllllll aaaa CCCCPPPPAAAANNNN mmmmoooodddduuuulllleeee????
-
- The easiest way is to have the CPAN module do it for you. This module
- comes with perl version 5.004 and later. To manually install the CPAN
- module, or any well-behaved CPAN module for that matter, follow these
- steps:
-
- 1 Unpack the source into a temporary area.
-
- 2
-
- perl Makefile.PL
-
-
- 3
-
- make
-
-
- 4
-
- make test
-
-
-
-
-
-
- PPPPaaaaggggeeee 11114444
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- 5
-
- make install
-
-
- If your version of perl is compiled without dynamic loading, then you
- just need to replace step 3 (mmmmaaaakkkkeeee) with mmmmaaaakkkkeeee ppppeeeerrrrllll and you will get a new
- _p_e_r_l binary with your extension linked in.
-
- See the _E_x_t_U_t_i_l_s::_M_a_k_e_M_a_k_e_r manpage for more details on building
- extensions, the question "How do I keep my own module/library directory?"
-
- HHHHoooowwww ddddoooo IIII kkkkeeeeeeeepppp mmmmyyyy oooowwwwnnnn mmmmoooodddduuuulllleeee////lllliiiibbbbrrrraaaarrrryyyy ddddiiiirrrreeeeccccttttoooorrrryyyy????
-
- When you build modules, use the PREFIX option when generating Makefiles:
-
- perl Makefile.PL PREFIX=/u/mydir/perl
-
- then either set the PERL5LIB environment variable before you run scripts
- that use the modules/libraries (see the _p_e_r_l_r_u_n manpage) or say
-
- use lib '/u/mydir/perl';
-
- See Perl's the _l_i_b manpage for more information.
-
- HHHHoooowwww ddddoooo IIII aaaadddddddd tttthhhheeee ddddiiiirrrreeeeccccttttoooorrrryyyy mmmmyyyy pppprrrrooooggggrrrraaaammmm lllliiiivvvveeeessss iiiinnnn ttttoooo tttthhhheeee mmmmoooodddduuuulllleeee////lllliiiibbbbrrrraaaarrrryyyy
- sssseeeeaaaarrrrcccchhhh ppppaaaatttthhhh????
-
- use FindBin;
- use lib "$FindBin:Bin";
- use your_own_modules;
-
-
- HHHHoooowwww ddddoooo IIII aaaadddddddd aaaa ddddiiiirrrreeeeccccttttoooorrrryyyy ttttoooo mmmmyyyy iiiinnnncccclllluuuuddddeeee ppppaaaatttthhhh aaaatttt rrrruuuunnnnttttiiiimmmmeeee????
-
- Here are the suggested ways of modifying your include path:
-
- the PERLLIB environment variable
- the PERL5LIB environment variable
- the perl -Idir commpand line flag
- the use lib pragma, as in
- use lib "$ENV{HOME}/myown_perllib";
-
- The latter is particularly useful because it knows about machine
- dependent architectures. The lib.pm pragmatic module was first included
- with the 5.002 release of Perl.
-
- HHHHoooowwww ddddoooo IIII ggggeeeetttt oooonnnneeee kkkkeeeeyyyy ffffrrrroooommmm tttthhhheeee tttteeeerrrrmmmmiiiinnnnaaaallll aaaatttt aaaa ttttiiiimmmmeeee,,,, uuuunnnnddddeeeerrrr PPPPOOOOSSSSIIIIXXXX????
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11115555
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- #!/usr/bin/perl -w
- use strict;
- $| = 1;
- for (1..4) {
- my $got;
- print "gimme: ";
- $got = getone();
- print "--> $got\n";
- }
- exit;
-
- BEGIN {
- use POSIX qw(:termios_h);
-
- my ($term, $oterm, $echo, $noecho, $fd_stdin);
-
- $fd_stdin = fileno(STDIN);
-
- $term = POSIX::Termios->new();
- $term->getattr($fd_stdin);
- $oterm = $term->getlflag();
-
- $echo = ECHO | ECHOK | ICANON;
- $noecho = $oterm & ~$echo;
-
- sub cbreak {
- $term->setlflag($noecho);
- $term->setcc(VTIME, 1);
- $term->setattr($fd_stdin, TCSANOW);
- }
-
- sub cooked {
- $term->setlflag($oterm);
- $term->setcc(VTIME, 0);
- $term->setattr($fd_stdin, TCSANOW);
- }
-
- sub getone {
- my $key = '';
- cbreak();
- sysread(STDIN, $key, 1);
- cooked();
- return $key;
- }
-
- }
- END { cooked() }
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11116666
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
- AUTHOR AND COPYRIGHT
- Copyright (c) 1997 Tom Christiansen and Nathan Torkington. All rights
- reserved. See the _p_e_r_l_f_a_q manpage for distribution information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11117777
-
-
-
-
-
-
- PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111)))) PPPPEEEERRRRLLLLFFFFAAAAQQQQ8888((((1111))))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 11118888
-
-
-
-
-
-
-